/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.core.entity;

import lombok.Data;
import org.codehaus.plexus.util.StringUtils;

import java.util.concurrent.ConcurrentHashMap;

public class HashLinkedNodeMap {
    private final ConcurrentHashMap<String, LinkedNode> linkedNodeMap = new ConcurrentHashMap<>();

    private final LinkedNode head;
    private LinkedNode last;

    // 若首节点不参与循环校验,则key为固定值,name为null
    public HashLinkedNodeMap() {
        this("rootMdpkg", null);
    }

    // 首节点参与循环校验
    public HashLinkedNodeMap(String indexKey, String rootNodeName) {
        put(indexKey, rootNodeName);
        head = last;
    }

    private void put(String indexKey, String name) {
        LinkedNode node = new LinkedNode(indexKey, name);
        if (last != null) {
            last.setNext(node);
            node.setPrev(last);
        }
        last = node;
        linkedNodeMap.put(node.getIndexKey(), node);
    }

    /**
     * 先判断map中是否存在,若不存在则写入,否则返回map中已存在的节点
     *
     * @param indexKey 节点索引编码
     * @return map中存在则返回已存在的节点, 否则返回null
     */
    public String putAfterCheckDup(String indexKey, String name) {
        final LinkedNode node = get(indexKey);
        if (node == null) {
            this.put(indexKey, name);
            return null;
        } else {
            node.setFlag(true);
            String errMsg = generatErrMsg(node.getNameWithFlag());
            node.setFlag(false);
            return errMsg;
        }
    }

    private String generatErrMsg(String dupMdPkgName) {
        LinkedNode node = this.head.getNext();
        StringBuilder sb = new StringBuilder();
        sb.append("当前工程");
        String headName = this.head.getNameWithFlag();
        if (StringUtils.isNotBlank(headName)) {
            sb.append("(").append(headName).append(")");
        }
        sb.append(" -> ");

        for (; node != null; node = node.getNext()) {
            sb.append(node.getNameWithFlag()).append(" -> ");
        }
        sb.append(dupMdPkgName);
        return sb.toString();
    }

    //删除最后一个节点
    public void removeLast() {
        // 不删除根节点
        if (last == head) {
            return;
        }
        linkedNodeMap.remove(last.getIndexKey());
        last = last.getPrev();
        last.setNext(null);
    }

    private LinkedNode get(String indexKey) {
        return linkedNodeMap.get(indexKey);
    }
}

@Data
class LinkedNode {
    private LinkedNode prev;
    private LinkedNode next;
    private String indexKey;
    private String name;
    private boolean flag;

    protected LinkedNode(String indexKey, String name) {
        this.indexKey = indexKey;
        this.name = name;
    }


    protected String getNameWithFlag() {
        if (name == null) {
            return "";
        }
        return flag ? "[" + name + "]" : name;
    }
}